<?php
/**
 * Date: 2024.8
 * Author: kahn
 * Bootstrap 引导启动程序
 */
use psr16Cache\RedisCache;
use psr16Cache\FileCache;
use think\facade\Db;

class Bootstrap extends Yaf_Bootstrap_Abstract {

    protected Yaf_Config_Abstract $config;

    /**
     * @param Yaf_Dispatcher $dispatcher
     * @return void
     */
    public function _initConfig(Yaf_Dispatcher $dispatcher): void
    {
        //把配置保存起来
        $this->config = Yaf_Application::app()->getConfig();
        Yaf_Registry::set('config', $this->config);
        //关闭自动加载模板
        $dispatcher->autoRender(false);

        //自动加载
        spl_autoload_register('Bootstrap::autoLoader', true, true);

        Yaf_Loader::import(APP_PATH . '/library/Function.php');
    }

    /**
     * 自定义自动加载函数
     * @param  $class
     * @return boolean
     */
    final public static function autoLoader($class): bool
    {
        $class = str_replace('\\', DS, $class);
        $classpath = APP_PATH . DS . $class . '.php';
        if (is_file($classpath)) {
            include $classpath;
        }
        return true;
    }

    /**
     * 插件注册, 修改时需注意插件执行顺序
     * @param Yaf_Dispatcher $dispatcher
     * @return void
     */
    public function _initPlugin(Yaf_Dispatcher $dispatcher): void
    {
        if ($this->config->application->benchmark) {
            $dispatcher->registerPlugin(new BenchmarkPlugin());
        }
        //cookie涉及HTTP请求，命令行下应禁用
        if ($dispatcher->getRequest()->getMethod() != 'CLI') {
            $dispatcher->registerPlugin(new AntizyPlugin());
        }

        $dispatcher->registerPlugin(new RoutePlugin());
        $dispatcher->registerPlugin(new JwtPlugin());

    }

    /**
     * 错误处理初始化
     * @param Yaf_Dispatcher $dispatcher
     * @return void
     */
    public function _initError(Yaf_Dispatcher $dispatcher): void
    {
        /**
         * 错误捕获机制:
         * 1. application.debug参数, true为开启, false为关闭
         *    该参数错误输出到前端, 还是只记录到log文件
         * 2. application.dispatcher.catchException参数, 1为开启, 0为不开启
         *    该参数开启后, error错误由Error控制器捕获. 只捕获致命错误和异常
         * 3. error_reporting(), 该系统函数配置系统记录错误的等级
         * 4. ini_set('display_errors', 1); 该系统函数设置是否把错误抛到前端, 注意, 这个设置不影响Error控制器工作
         * 5. ini_set('error_log', $fname); 该系统函数设置错误日志记录文件
         */
        error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); //设置错误日志等级
        if ($this->config->application->debug) {
            define('DEBUG_MODE', true);
            ini_set('display_errors', 1);
        } else {
            define('DEBUG_MODE', false);
            ini_set('display_errors', 0);
        }
        ini_set('error_log', LOG_PATH . '/error-'. date('Ymd') . '.log'); //定向错误日志存储文件
    }


    /**
     * 初始化Orm
     * @param Yaf_Dispatcher $dispatcher
     * @return void
     */
    public function _initOrm(Yaf_Dispatcher $dispatcher): void
    {
        //表结构缓存入redis
        //Db::setCache(new RedisCache($this->config->cache->orm->toArray()));
        //表结构缓存入文件
        {
            $config = $this->config->cache->orm->toArray()[2];
            $config['cachePath'] = ROOT_PATH . DS .$config['cachePath'];
            Db::setCache(new FileCache($config));

        }

        //初始化Orm
        $default = 'default';
        $tiku = $this->config->database->$default->toArray();
        Db::setConfig([
            'default'     => $default,
            'connections' => [
                $default => $tiku,
            ],
        ]);

        //设置监听, 记录sql
        Db::listen(function($sql, $runtime, $master) {
            if(DEBUG_MODE || $runtime > 1) //debug开启或者sql执行时间大于1秒, 记录日志
                Log::info("TIME: $runtime\r\nSQL: $sql");
        });
    }

}
